package school.course;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import school.DateComparator;
import school.Instructor;
import school.Student;


public abstract class AbstractSimpleCourse implements Course {

	protected Date endDate = null;
	protected Date startDate = null;
	
	protected Instructor instructor=null;
	protected List<Session> sessions = new LinkedList<Session>();
	protected List<Student> students = new LinkedList<Student>();
	
	private DateComparator dtComparator = new DateComparator();
	
	@Override
	public Date getEndDate() {
		return endDate;
	}

	@Override
	public boolean setInstructor(Instructor instructor) {
		if (getInstructor()!=null){
			getInstructor().removeCourse(this);
		}
		if (instructor!=null){
			instructor.addCourse(this);
		}
		this.instructor= instructor;
		return true;
	}

	@Override
	public Instructor getInstructor() {
		return instructor;
	}

	@Override
	public Session[] getSessions() {
		Session[] sessionArray={};
		return sessions.toArray(sessionArray);
	}

	@Override
	public Date getStartDate() {
		return startDate;
	}

	@Override
	public Student[] getStudents() {
		Student[] studentArray={};
		return students.toArray(studentArray);
	}

	/* end date can only be set after the start date is set
	 * end date can be either null or not before start date
	 */
	@Override
	public void setEndDate(Date endDate) throws RuntimeException, NullPointerException {
		if (getStartDate()==null){
			if (endDate==null){
				this.endDate=null;
			}
			else{
				throw new NullPointerException("State date is null");
			}
		}
		else {
			if (endDate !=null && dtComparator.compare(getStartDate(), endDate)>0) {
				throw new RuntimeException("Start date: "+getStartDate().toString()+" is after end date: "+getEndDate().toString());
			}
			else {
				this.endDate=endDate;
			}
		}
	}

	/* start date can be either null or not before start date
	 * set start date to null also sets end date to null
	 */
	@Override
	public void setStartDate(Date startDate) throws RuntimeException {
		if (startDate==null){
			this.startDate=null;
			try {
				setEndDate(null);				
			} catch (Exception e) {
				return;
			}
		}
		else {
			if (dtComparator.compare(startDate, getEndDate())>0) {
				throw new RuntimeException("Start date: "+getStartDate().toString()+" is after end date: "+getEndDate().toString());
			}
			this.startDate = startDate;
		}
	}

	@Override
	public boolean isEndsAfter(Date date) {
		Date endDate = getEndDate();
		if (endDate==null) {
			return true;
		}
		return (dtComparator.compare(getEndDate(), date)>-1);
	}

	@Override
	public boolean isStartsBefore(Date date) {
		Date startDate = getStartDate();
		if (startDate==null) {
			return true;
		}
		return (dtComparator.compare(getStartDate(),date)<1);
	}

}
